The other topics in this chapter are:
You can also view the corresponding assembly-language instructions and memory addresses. See "Viewing source code as assembly" on page 402 for more information.
CodeWarrior supports several different symbolics formats appropriate for a variety of build targets. Table 11.1 lists some of the supported formats:
Format
|
Principal Build Target
|
---|---|
See "Preparing for Debugging" on page 390 for information on how to set up projects and source files to create symbolics files.
For more information on compiler and linker settings, refer to "Configuring Target Options" on page 315.
This section discusses the following topics:
To prepare a build target for debugging, make sure it is the active build target. Then, choose the Enable Debugger
command from the Project menu. When debugging is enabled for a build target, the menu command changes to
Disable Debugger
. Choosing Disable Debugger
turns off debugging for the build target and changes the menu command back to Enable Debugger
.
See "Configuring Target Options" on page 315 for more information on build target settings.
When you choose Enable Debugger,
you might see an alert (Figure 11.1). CodeWarrior is reminding you that it will modify the build target settings to prepare the project for debugging. Click Yes to apply the debugging changes to your build target.
Enable Debugger
The Project window includes a debug column, as shown in Figure 11.2. For files, a mark in this column means that symbolic information is generated; no mark means that symbolic information is not generated. For group names, a mark indicates that debugging is enabled for every file in the group and no mark means that debugging is disabled for one or more files in the group.
To generate symbolics information, both the current build target and the source files within that target must be prepared for debugging. See Setting Up a File for Debugging to learn how to do this.
For more information on compiling and linking, see "Configuring Target Options" on page 315 as well as the Targeting manual for your particular platform target.
To debug a project, you must first enable debugging for that project. Choose Enable Debugger
from the Project menu to enable debugging. After debugging is enabled, the
Enable Debugger
command changes to Disable Debugger
.
When you enable debugging, the Run command in the Project menu changes to Debug. The Debug
command compiles and links your project, generates a symbolics file, and activates the debugger. The debugger automatically loads the symbolics file so that you can debug your project. See "Preparing for Debugging" on page 390 for more information on this topic.
1. Open the Target Settings window for the project.
2. Display the Runtime Settings panel.
When the debugger opens a symbolics file, it opens a Stack Crawl window (formerly known as the Program window). This window is shown in Figure 11.3. The debugger allows more than one symbolics file to be open at a time: that is, you can debug more than one program at a time. For example, you can use this feature to debug an application and separate plug-ins for the application. A Stack Crawl is displayed for each active symbolics file and each thread.
You can resize panes by clicking and dragging the resize bar between them. Use the Tab key to switch keyboard focus between panes.The active pane has a heavy border.
You can also use Control-Tab as another way to navigate through items in an active Stack Crawl pane or Variables pane. To learn more about customizing key bindings, see "Customizing Key Bindings" on page 297.
The debugger toolbar (Figure 11.4) contains shortcut buttons for commonly used commands from the Project and Debug menus: Run, Stop, Kill, Step Over, Step Into,
and Step Out.
Choose Window > Toolbar >
Show Window Toolbar
to display the toolbar. To hide the toolbar, choose
Window > Toolbar >
Hide Window Toolbar.
For more information, see "Basic Debugging" on page 427.
The Stack Crawl window includes a Stack Crawl pane. This pane displays the current subroutine calling chain (Figure 11.5). Each subroutine is placed below the routine that called it. Select any routine in the Stack Crawl pane to display its code in the Source pane.
The Variables pane displays a list of local variables used in the program. The listing of these variables is controlled by the Variables Pane Listing icon (), shown in Figure 11.6. Clicking this icon toggles the list in the Variables pane between Variables:All and
Variables:Auto. These two list types are described in Table 11.2.
Type
|
Variables Listed
|
---|---|
Current-statement arrow is currently located |
For example, in Figure 11.6, clicking the hierarchical control next to the variable msg hides its members. Click the hierarchical control again to display the members. You can dereference multiple levels of pointers to get directly to the data by pressing the Ctrl/Option key while expanding an entry. This feature is useful for expanding a handle to a structured type and viewing the structure's members.
The Source pane in the Stack Crawl window displays source code. The debugger takes the source code directly from the current build target's source code files, including any comments and white space. The pane shows C/C++, Pascal, Java, and in-line assembly code exactly as it appears in your program's source code (Figure 11.7), using the font and color specified in the IDE's Editor Settings panel.
Click the Source pane disclosure triangle, shown in Figure 11.3 on page 397, to display or hide the Source pan. If you hide the Source pane, the debugger opens both an editor window and a Stack Crawl window the next time you start a debugging session. The editor window displays the same source code and breakpoints as the Source pane.
To view your source code as assembly language, click the Source pop-up menu at the bottom of the Stack Crawl window. Choose Assembler
to display the contents of the Source pane as assembly code (Figure 11.8). While viewing assembly code, the debugger still lets you step through the code and set breakpoints, one routine at a time.
To view your source code and assembly language together, click the Source pop-up menu at the bottom of the Stack Crawl window. Choose Mixed
to display the source code of the current routine intermixed with assembly code (Figure 11.9). The source code that produced the assembly instructions appears before the assembly itself. When viewing code in mixed view, you can set breakpoints and step through code, but only for assembly language instructions. Notice you cannot set breakpoints on source code lines, as shown in Figure 11.9.
The Function pop-up menu, at the bottom-left corner of the Source pane, contains a list of the routines defined in the source file selected in the Source pane (Figure 11.10). Selecting a routine in the Function pop-up menu displays that routine in the Source pane.
Alt/Option click the Function pop-up menu to display the menu items in alphabetical order.
When you double-click a symbolics file, the debugger opens a Source Code Browser window, as shown in Figure 11.11.
The Source Code Browser window somewhat resembles the Stack Crawl window in both appearance and functionality, but displays different information. The Source Code Browser window lets you view any file in the current build target, whereas the Stack Crawl window can only display the file containing a routine selected from the Stack Crawl pane. You can also use the Source Code Browser window to view or edit the values of all of your program's global variables; the Stack Crawl window lets you change only those global variables referenced by active routines in the call chain. For more information about viewing global variables, see "Global Variables Window" on page 412.
Do not confuse the Source Code Browser window with the Class Browser window. Although the two look similar, the Source Code Browser window opens only when you double-click a symbolics file.The Source Code Browser window has three panes:
The active pane has a heavy border.
To learn more about the contents of the Stack Crawl window, refer to "Stack Crawl Window" on page 395.
The Files pane in the Source Code Browser window (Figure 11.12) displays a list of all source files associated with the current build target you are debugging. When you select a file name in this pane, the Functions pane displays a list of the routines declared in the file.The Files pane is used in conjunction with the Functions and Source panes to set breakpoints in your program.
For more information, see "Global Variables Window" on page 412 and "Breakpoints" on page 442.
When you select a source code file in the Source Code Browser window's File pane, the Functions pane (Figure 11.13) presents a list of all routines defined in that file. Clicking a routine name displays that routine in the Source pane at the bottom of the window.
className::methodName
by method name instead of by class name.
The Source pane in the Source Code Browser window allows you to browse the contents of the source code file selected in the Files pane (Figure 11.14). You can use it to set breakpoints in any file listed in the Files pane. To learn how to set breakpoints, refer to "Breakpoints" on page 442.
Notice, however, that the Source pane does not show the currently executing statement. The current-statement arrow in the Stack Crawl window shows the currently executing statement. You can also use the Stack Crawl window to view local variables. For more information, see "Stack Crawl Window" on page 395.The Source pane displays code in the font and colors specified in the panels of the IDE Preferences window. For more information, see "Editor Settings" on page 269 and "Display Settings" on page 279.
The bottom of the Source Code Browser window has a Source pop-up menu like the one in the Stack Crawl window (see "Viewing source code as assembly" on page 402). Choose Assembler
to display the contents of the source pane as assembly code, as shown earlier in Figure 11.8 on page 402. You can set breakpoints in assembly code, just as you can in source code. Choose Mixed
to display source code intermixed with assembly language, as shown earlier in Figure 11.9 on page 403.
Alt/Option click the Function pop-up menu to display the menu sorted alphabetically, as shown earlier in Figure 11.10 on page 404.
When you debug source code, the debugger displays useful information about your program's variables. This information is displayed automatically as you move the cursor over particular variables in source code views. For example, suppose you start a debugging session and examine your source code in the Source pane of the Stack Crawl window. When you position the cursor over the variable i
, as shown in Figure 11.15, the debugger displays the current value of that variable.
The debugger includes a contextual menu (Figure 11.16) that provides convenient access to various debugging commands. To display the contextual menu:
Control-click an item, or click and hold on an item.
Control-click an item, or click and hold on an item.
The Expressions window (Figure 11.17) provides a single place to put frequently used local variables, global variables, structure members, and array elements without opening and manipulating several windows.
To open the Expressions window, choose Expressions Window
from the Window menu.
Use the Copy to Expression
command in the Data menu to add selected items to the Expressions window. Alternatively, you can select the same command from the debugger contextual menu (Figure 11.16 on page 411). You can also use the mouse to drag and drop items from other variable panes and windows into the Expressions window. To reorder items in the Expressions window, drag each item to its new position in the list.
To learn about the Expressions window, refer to "Using the Expressions window" on page 461.
The Global Variables window (Figure 11.18) displays all global variables used by your program. You can also view static variables by selecting a file in the File pane. The static variables are displayed in the Variables pane.
To display a global variable in its own window, double-click the variable's name in the Variables pane. A new Variable window opens and displays the variable's name and value. You can also open a Variable window by selecting the desired variable in the Variables pane and selecting the View Variable
or View Array
commands from the Data menu or the debugger contextual menu (Figure 11.16 on page 411). A global variable displayed in its own window can be viewed and edited the same way as in the Variables pane. You can also add global variables to the Expressions window.
For more information, refer to "Expressions Window" on page 411, "Variable Window" on page 416, and "Array Window" on page 417.
The Breakpoints window (Figure 11.19) lists the breakpoints in your current build target by source file and line number. To open the Breakpoints window, choose Breakpoints Window
from the Window menu.
For more information, see "Breakpoints" on page 442, "Show Breakpoints" on page 620, "Hide Breakpoints" on page 620, and "Conditional breakpoints" on page 446.
The Watchpoints window (Figure 11.20) lists the watchpoints in your current build target by memory address. To open the Watchpoints window, choose Watchpoints Window from the Window menu.
You can clear a watchpoint by selecting it and doing any of the following:
Clear Watchpoint
from the Debug menu.
Clear
from the Edit menu.
The Log window (Figure 11.21) displays messages as your program makes calls to system DLLs or starts new tasks.
To use the Log window, you need to configure your project to display log information. You must enable the Log System Messages preference in the Debugger Settings preference panel. See "Debugger Settings" on page 353 for more information.
printf()
messages. In the Mac OS, log information refers to messages about the loading of PowerPC code fragments, as well as DebugStr()
messages.
The Variable window (Figure 11.22) displays a single variable and allows you to edit its contents. A Variable window containing a local variable will close on exit from the routine in which the variable is defined.
The Array window (Figure 11.23) displays a contiguous block of memory as an array of elements and allows you to edit the contents of those elements. To open the Array window, select an array variable in a Variables pane (either locals or globals) and then choose View Array
from the Data menu.
You can also use the View Memory As
command in the Data menu to open an array window. This command presents a dialog box which lets you select a data type, then opens an Array window interpreting memory as an array of that type. For more information, see "View Memory As" on page 623.
The Memory window displays the contents of memory in hexadecimal and corresponding ASCII character values (Figure 11.24). To open a Memory window, select a variable, routine name, or expression representing the desired base address in the Program, Source Code Browser, or Expressions window and choose View Memory
from the Data menu.
View Memory As
command opens an Array window ("Array Window" on page 417) displaying memory as an array of data of a type you specify.
PlayerRecord
will show memory beginning at the address of PlayerRecord
.
*myArrayPtr
will show memory beginning at the address of the object pointed to by myArrayPtr
.
The General Registers window (Figure 11.25) displays CPU registers and allows you to edit register contents. To open a General Registers window, choose Window > Registers Windows > General Registers
.
Register Window
to see the window shown in Figure 11.25.
For PowerPC build targets, the General Registers window is shown in Figure 11.26. You can toggle the bit values of the XER and condition registers between 0 and 1. Select the bit you want to change and press Return or Enter. You can also double-click the bit to toggle its value.
The FPU Registers window (Figure 11.29) displays FPU registers and allows you to edit register contents. To open an FPU Registers window, choose Window > Registers Windows > FPU Registers
.
FPU Registers Window
to see the window shown in Figure 11.29.
The Processes window (Figure 11.29) lists currently running processes, including some hidden processes. The Processes window also lists tasks for a selected process. To open the Processes window, choose Processes Window
from the Window menu.
The Processes window has two panes and a toolbar:
The Processes window toolbar (Figure 11.30) has controls to attach debugging sessions to selected processes and to open the Stack Crawl window.
The Task pane lists all the active tasks for a given process. Only tasks from programs under the debugger's control are shown. Double-clicking a task name activates a Stack Crawl window with the code for that task. You can also choose a task and then click the Stack Crawl window button (Figure 11.30).
Debug
from the Project menu to debug a project, the debugger displays the Stack Crawl Window. Typically, the debugger stops the program's execution at the first line of code in the main
function. If you encounter this situation, all is well. Your program's code is stopped and ready to run.
Debug
from the Project menu or click the Run button in the Debugger toolbar. Then, the debugger launches the build target, takes control of that build target, brings the Stack Crawl window to the front, and stops the program at the first line.
The debugger might ask you for the location of a particular file, as shown in Figure 11.33 (Windows) or Figure 11.34 (Mac OS).
You might see this dialog either upon startup (the debugger is looking for the file with the main entry point) or by clicking on a specific file in the Source Code Browser Window.
The debugger might ask you to locate files in these situations:
For more information, see "Generating Symbolics Information" on page 393.
To step through your code, you can use the debugger toolbar buttons, the keyboard, or choose the appropriate menu command. Table 11.3 lists the debugger toolbar buttons along with their Debug menu commands and their default keyboard equivalents.
Button
|
Menu Command |
Windows Keyboard Equivalen
|
Mac OS Keyboard Equivalent
|
Solaris Keyboard Equivalent
|
---|---|---|---|---|
The current-statement arrow in the Stack Crawl window (Figure 11.35) indicates the next statement to be executed. It represents the processor's program-counter register. When you begin a debugging session, the current-statement arrow points to the first line of executable code in your program.
If the program is running but its execution has stopped, use the Run
command (Figure 11.36) to restart your program. The program resumes execution at the current-statement arrow.
Run
command
After a breakpoint or a Stop
command, the debugger regains control and displays the Stack Crawl window with the current-statement arrow and the current values of variables. The debugger places an implicit breakpoint at the program's main entry point and stops there (Figure 11.37). Issuing another Run
command resumes program execution from the point of the interruption. After a Kill
command, Run
restarts the program from its beginning.
Automatically launch applications when SYM file opened
preference (see "Global Settings" on page 283). One use for this feature is to debug C++ static constructors, which are executed before entering the program's main routine.
To execute one statement, use the Step Over
command (Figure 11.38). If the statement is a routine call, the entire called routine executes and the current-statement arrow proceeds to the next line of code. In other words, the Step Over
command executes a routine call without visiting the code in the called routine. This behavior holds true if the routine does not have breakpoints and does not call other routines. When you step over code and reach the end of a routine, the current-statement arrow returns to the routine's caller.
Step Over
command
Sometimes you want to follow execution into a called routine. To execute one statement at a time and follow execution into a routine call, use the Step Into
command (Figure 11.39).
Step Into
command
To execute statements until the current routine returns to its caller, use the Step Out
command (Figure 11.40). Step Out
executes the rest of the current routine normally and stops the program when the routine returns to its caller. You go one level back up the calling chain. See "Call-chain navigation" on page 438 for more information.
Step Out
commandSometimes you may want to skip statements altogether and not execute them at all. To move the current-statement arrow to a different part of the currently executing source code, simply drag it to a new position, as shown in Figure 11.41. Note that dragging the current-statement arrow up or down does not execute the statements between the arrow's original position and its new position.
To move the current-statement arrow without potentially corrupting the run-time environment, Alt/Option click a statement in the Breakpoint column (Figure 11.42). Alt/Option clicking the statement sets a temporary breakpoint: Execution proceeds normally until the current-statement arrow reaches the temporary breakpoint, then stops. After execution stops, the temporary breakpoint is automatically removed. For more information, see "Breakpoints" on page 442.
While your program is running, you can use the Stop
command (Figure 11.43) to suspend execution and explore your code with the debugger. You can then step through your code from that point, or use the Run
command to resume execution.
Stop
command
Stopping in this manner is not very precise. Code executes very quickly, and there is no telling exactly where your program is suspended when you issue the Stop
command. Instead of stopping code, you can use breakpoints, which allow you to suspend a program's execution at a specific point. To learn more, see "Breakpoints" on page 442.
Stop
command is not available for some build targets because it is dependent on operating system services. For details on any particular build target, see the corresponding Targeting manuals as described in "Targeting Documentation" on page 27.
Sometimes you want to terminate your program completely and end the debugging session. The Kill
command (Figure 11.44) ends the program and returns control to the debugger. The Stack Crawl window tells you when the program is running, and to choose Stop
from the Debug menu to stop it.
"Stepping through a single line" on page 433, "Stepping into routines" on page 434, and "Stepping out of routines" on page 434 describe various ways to linearly navigate through your code.
The chain of routine calls is displayed in the Stack Crawl pane of the Stack Crawl window (Figure 11.45). Each routine in the chain is displayed below its caller, so the currently executing routine is at the bottom of the chain and the first routine to execute in the program is at the top.
You can use the Stack Crawl pane to navigate to the routines that called the halted routine. To find the point where a routine in the Stack Crawl pane is called, click the name of the routine's caller. The source code for the caller is displayed in the Source pane, right at the point of the call (Figure 11.46).
1. Make the Source Code Browser window active (Figure 11.47).
2. In the Source Code Browser window's Files pane, select the file where the routine is defined (Figure 11.48).
3. Locate the desired code in the source file.
Scroll through the Source pane to find the code you want. A more useful technique is to use the Source Code Browser window's Functions pane or Function pop-up menu to select the desired routine (Figure 11.49). The routine is displayed in the Source pane, allowing you to set and clear breakpoints. For more information, see "Breakpoints" on page 442.
For more information, see "Editor Preferences" on page 268.
From the Source pane of the editor window, Stack Crawl window, or Source Code Browser window, you can set a breakpoint on any line with a dash marker-the short line to the left of a statement in the Breakpoint column (see Figure 11.50). The dash becomes a dot (on color monitors, the default dot color is red). This dot indicates that a breakpoint has been set at this statement. Execution will stop just before this statement is executed.
You can manipulate breakpoints with the following commands in the Debug menu:
Clear Breakpoint
-removes the breakpoint from the current line
Enable Breakpoint
-makes the breakpoint on the current line active
Disable Breakpoint
-makes the breakpoint on the current line inactive
Clear All Breakpoints
-removes all breakpoints from the current program
Show Breakpoints
-displays the Breakpoint column when it is currently hidden
Hide Breakpoints
-removes the Breakpoint column when it is currently visible
To see a list of all active breakpoints in your program, choose the Breakpoints Window
command from the Window menu. The debugger displays a window that lists the source file and line number for each breakpoint (Figure 11.51). Clicking a breakpoint marker in the Breakpoints window toggles the breakpoint's status between active and inactive. A dot indicates that the breakpoint is active. The debugger stops the program's execution upon reaching an active breakpoint. A circle indicates that the breakpoint is inactive. The debugger continues to execute the program without stopping at an inactive breakpoint. The debugger remembers the position of inactive breakpoints in the program.
For more information, see "Breakpoints Window" on page 413.
Conditional breakpoints are created in the Breakpoints window. To specify a conditional breakpoint:
1. Set a breakpoint at the desired statement.
2. Display the Breakpoints window by choosing Breakpoints Window
from the Window menu.
In Figure 11.52, the debugger stops execution at line 162 in the NewBall()
routine if and only if the variable newTop
is greater than six.
You can set breakpoints for templated functions as well as functions that have been redefined.
For example, suppose you have a file named file.h
that defines a function void FOO(args)
, where FOO
is a macro. If you create the lines of code shown in Listing 11.1, a pop-up menu appears in the Breakpoints column during the debugging session. This pop-up menu lets you choose whether to set a breakpoint for function1
or function2
.
#define FOO function1
#include file.h
#define FOO function2
#include file.h
Normally, when debugging information is enabled for a source file, the compiler tries to start a new statement block at each source statement that actually generates some code. For example, consider the source code in Listing 11.2:
- int i = 1;
- if (i)
{ //This is the third line.
int k;
- int j = 1;
- i = j;
}
After you start optimizing the code, the situation changes. For example, when you enable Instruction Scheduling in the project's Global Optimizations preference panel, the compiler no longer starts a new basic block for each source statement. The scheduler gains the maximum flexibility for reordering instructions within the block. The different instructions that correspond to a source statement are no longer consecutive. Instead, they are intermingled with the instructions from other source statements. Because of these optimizations, the debugger no longer displays breakpoint dashes as shown in Listing 11.2.
i = 0;
j = 0;
while (i < 10)
{
j = j + 1;
i = i + 1;
}
With minimal optimization, the compiler translates the code from Listing 11.3 into the following equivalent code:
j = j + 1; // duplicate 10 times
j = j + 1;
.
.
.
j = j + 1;
j = 10;
While debugging your code, you should disable optimizations or use optimizations that are "debug safe." Different optimizations are available for different build targets. See the appropriate Targeting manual for additional details, as described in "Targeting Documentation" on page 27.
You can view the current optimizations for your project in the Global Optimizations preference panel of the Target Settings window. For more information, refer to "Configuring Target Options" on page 315.
After setting a breakpoint, you can continue debugging the program. Refer to "Running, Stepping, and Stopping Code" on page 430 for additional details.
A watchpoint is a location or region of memory that you want the debugger to observe for you. Whenever a new value is written to that area of memory, the debugger suspends execution of the program and notifies you with an alert message on your screen (Figure 11.53). After dismissing the alert, you can examine the call chain, inspect or change variables, step through your code, or use any of the debugger's other facilities. (In particular, from the debugger level, you can change the contents of the location that triggered the watchpoint without triggering it again.) Use the Run
command (or the Run button on the debugger toolbar) to continue execution from the watchpoint.
The following sections discuss watchpoints in more detail:
You can set a watchpoint in any of the following ways:
Set Watchpoint
from the Debug menu.
Set Watchpoint
from the Debug menu.
Set Watchpoint
command.
You can clear a watchpoint in any of the following ways:
Clear Watchpoint
command from the Debug menu.
Clear Watchpoint
from the Debug menu.
Clear Watchpoint
from the Debug menu
¯ Choose Clear
from the Edit menu
¯ Press the Backspace/Delete key
Clear Watchpoint
command.
To see a list of all watchpoints currently set in your program, choose the Watchpoints Window command from the Window menu. The debugger displays the Watchpoints window (Figure 11.54).
For more information, see "Watchpoints Window" on page 414.
This section discusses the following topics:
Local variables are displayed in the Variables pane of the Stack Crawl window (Figure 11.55). If the variable is a handle, pointer, or structure, you can click the hierarchical control to the left of the name to expand the view. This allows you to see the members of the structure, or the data referenced by the pointer or handle.
To learn some useful tips for using hierarchical controls, see "Expanding and Collapsing Groups" on page 74. For more information about the Variables pane of the Stack Crawl window, refer to "Variables pane" on page 398.
To view global variables, choose Global Variables Window
from the Window menu. Next, click the Global Variables item in the File pane (Figure 11.56). Then, the Variables pane displays the global variables in your program.
For more information, refer to "Global Variables Window" on page 412.
To place a variable or memory location in its own window, double-click its name (Figure 11.57) or select the name and choose the View Variable
command from the Data menu or the debugger contextual menu (Figure 11.16 on page 411). If the variable is an array, use the View Array
command instead. To view the memory the variable occupies as a memory dump, use either the View Memory
or View Memory As
command.
For more information, see "Variable Window" on page 416, "Array Window" on page 417, and "Memory Window" on page 418.
If you wish, the debugger can display the data types of variables on a window-by-window basis. Select the window or pane in which you want data types displayed and choose Show Types
from the Data menu or the debugger contextual menu (Figure 11.16 on page 411). Then, the names of the variables and memory locations in that window or pane are followed by the relevant data type (Figure 11.58).
In variable panes, show variable types by default
See "Display Settings" on page 279 for more information.
You display a variable's value in several formats:
Fixed
Fract
1. Select the item in a window or pane.
2. Choose View As
from the Data menu.
Alternatively, you can use the debugger contextual menu (Figure 11.16 on page 411) to select the same command. After you select View As
, the debugger displays the View As dialog box, shown in Figure 11.60.
3. Select the data type by which to view the item.
The display of the item's value changes to the specified type.
You can change the value of a variable in any variable view. Variables are displayed in several debugging windows: the Variables pane of the Stack Crawl window or Source Code Browser window, a Variable window, an Array window, or the Expressions window. To change the value, double-click the variable (or select it and press Enter/Return) and type the new value (Figure 11.61).
You can enter variable values in any of the following formats:
To enter a string or character constant, you must include C-style quotation marks (single quotes''
for a character constant, double quotes ""
for a string). For Pascal strings, include the escape sequence \p
as the first character in the string.
nil
and crash the machine.
The Expressions window provides a single place to put frequently used local variables, global variables, structure members, array elements, and complex expressions without opening and manipulating several windows. To open this window, choose Expressions Window
from the Window menu. You can add an item to the Expressions window by dragging and dropping that item from another window, or by selecting the item and choosing Copy to Expression
from the Data menu or the debugger contextual menu (Figure 11.16 on page 411).
Copy to Expression
and View As
commands in the Data menu and the debugger contextual menu.
To examine and change the raw contents of memory:
1. Select an item or expression representing the base address of the memory you want to examine.
2. Choose View Memory
from the Data menu.
1. Select the value of the variable or register in a window in which it is displayed.
2. Choose View Memory
or View Memory As
from the Data menu.
If you choose View Memory,
a Memory window opens displaying a raw memory dump starting at the address referenced by the pointer. If you choose View Memory As,
a dialog box opens and asks you to select a data type (Figure 11.62); continue with step 3.
3. If you chose View Memory As
, select a data type in the View As dialog box.
A new window opens (Figure 11.63) and displays the contents of memory, starting at the address referenced by the pointer.
For more information, refer to "Memory Window" on page 418.
To view the contents of the processor's general registers, choose Window > Registers Windows > General Registers
from the Window menu (Figure 11.64).
For more information, see "Register Windows" on page 421.
You can specify that a third-party editor open the file. See "IDE Extras" on page 254 for more information.
The debugger interprets expressions in various ways, depending on their locations:
1. Choose Expressions Window
from the Window menu.
If the Expressions window is already open, click it to make it active.
2. Choose New Expression
from the Data menu.
3. Type a new expression and press Enter/Return.
The expression's value is displayed in the Value column next to that expression (Figure 11.65). You can also create a new expression by dragging a variable or expression from another window to the Expressions window.
For more information, see "Expressions Window" on page 411.
If the expression yields a false (zero) result, the debugger ignores the breakpoint and continues execution. If the result is true (nonzero), the debugger stops at the breakpoint if the breakpoint is active. To learn how to set a breakpoint, see "Setting and clearing breakpoints" on page 443.
You can attach an expression to a breakpoint to make the breakpoint conditional on that expression:
1. Choose Breakpoints Window from the Window menu.
If the Breakpoints window is already open, click it to make it active.
Double-click the condition field for the desired breakpoint and type an expression (Figure 11.66). You can also add or change a breakpoint's condition by dragging an expression from another window and dropping it on the breakpoint's condition.
For more information, refer to "Breakpoints Window" on page 413 and "Conditional breakpoints" on page 446.
1. Choose View Memory
from the Data menu.
If a Memory window is already open, click it to make it active.
Refer to "Memory Window" on page 418 for more information.
Expressions can refer to specific items:
short
data type to denote a 2-byte integer value.
double
values as objects 10 bytes (80 bits) in length, rather than 8 bytes (64 bits).
==
(equal) and !=
(not equal) operators. Note that the debugger distinguishes between Pascal- and C-format strings. Use the prefix \p
when comparing Pascal string literals. The expression
"Nov shmoz ka pop" == "\pNov shmoz ka pop"
®
symbol and a register name. (Type Option-r
to get the ®
symbol.)
Expressions have the following limitations:
#define
directive). They are not available to the expression evaluator, even though they are defined in the source code.
i++
) and decrement (i--
) operators, as well as assignments (i = j
), are not allowed.
// The debugger cannot distinguish between x the
// int variable and x the double variable. If x is
// used in an expression, the debugger will not
// know which one to use.
void f(void)
{
int x = 0;
.
.
.
{
double x = 1.0;
.
.
.
}
}
// Use long in expressions; Int32 not available
typedef long Int32;
// Use Rect* in expressions; RectPtr not available
typedef Rect* RectPtr;
Inner
, not Outer::Inner
in a debugger expression.
// To refer to the i member, use Inner.i,
// not Outer::Inner.i
struct Outer
{
struct Inner
{
int i;
};
};
The list below provides example expressions that you can use in any window that uses expressions.
160
0xA0
myVariable
myVariable << 4
myRect.bottom - myRect.top
(foo > bar) ? foo : bar
*MyTablePtr
sizeof(myRect)
myRectPtr->bottom
(*myRectPtr).bottom
myDrawing::theRect
Below are examples of logical expressions: the result is considered true if non-zero, false if zero.
!isDone
isDone == 0
isReady
isReady != 0
foo >= bar
(foo
< bar) && (foo < car)
((char)foo >> 3) & 0x01
cstr == "Nov shmoz ka pop"
pstr == "\pScram gravy ain't wavy"
1
0
<>
) are defined elsewhere.
<name>
identifier
<qualified-name>
The following list describes expression syntax:
<name>
identifier
<qualified-name>
<typedef-name>
identifier
<class-name>
identifier
<qualified-name>
<qualified-class-name>::
<name>
<qualified-class-name>
<class-name>
<class-name>::
<qualified-class-name>
<complete-class-name>
<qualified-class-name>
::
<qualified-class-name>
<qualified-type-name>
<typedef-name>
<class-name>::
<qualified-type-name>
<simple-type-name>
<complete-class-name>
<qualified-type-name>
char
short
int
long
signed
unsigned
float
double
void
<ptr-operator>
*
&
<type-specifier>
<simple-type-name>
<type-specifier-list>
<type-specifier> <type-specifier-list>(
opt)
<abstract-declarator>
<ptr-operator> <abstract-declarator>(opt)
(<abstract-declarator>)
<type-name>
<type-specifier-list> <abstract-declarator>(
opt)
<literal>
integer-constant
character-constant
floating-constant
string-literal
<register-name>
®PC
®SP
®Dnumber
®Anumber
<register-name>
®R
number
®FPR
number
®RTOC
<register-name>
$PC
$SP
$RTOC
$Anumber
<primary-expression>
<literal>
this
::
identifier
::
<qualified-name>
(
<expression>)
<name>
<register-name>
<postfix-expression>
<primary-expression>
<postfix-expression>[
<expression>]
<postfix-expression>.
<name>
<postfix-expression>->
<name>
<unary-operator>
*
&
+
-
!
~
<unary-expression>
<postfix-expression>
<unary-operator> <cast-expression>
sizeof
<unary-expression>
sizeof(
<type-name>)
<cast-expression>
<unary-expression>
(
<type-name>)
<cast-expression>
<multiplicative-expression>
<cast-expression>
<multiplicative-expression> *
<cast-expression>
<multiplicative-expression> /
<cast-expression>
<multiplicative-expression> %
<cast-expression>
<additive-expression>
<multiplicative-expression>
<additive-expression> +
<multiplicative-expression>
<additive-expression> -
<multiplicative-expression>
<shift-expression>
<additive-expression>
<shift-expression> <<
<additive-expression>
<shift-expression> >>
<additive-expression>
<relational-expression>
<shift-expression>
<relational-expression> <
<shift-expression>
<relational-expression> >
<shift-expression>
<relational-expression> <=
<shift-expression>
<relational-expression> >=
<shift-expression>
<equality-expression>
<relational-expression>
<equality-expression> ==
<relational-expression>
<equality-expression> !=
<relational-expression>
<and-expression>
<equality-expression>
<and-expression> &
<equality-expression>
<exclusive-or-expression>
<and-expression>
<exclusive-or-expression> ^
<and-expression>
<inclusive-or-expression>
<exclusive-or-expression>
<inclusive-or-expression> |
<exclusive-or-expression>
<logical-and-expression>
<inclusive-or-expression>
<logical-and-expression> &&
<inclusive-or-expression>
<logical-or-expression>
<logical-and-expression>
<logical-or-expression> ||
<logical-and-expression>
<conditional-expression>
<logical-or-expression>
<logical-or-expression> ?
<expression> :
<conditional-expression>
<expression>
<conditional-expression>
.(x)sym
files, .dbg
files, preferences, binaries in your project (by choosing Remove Object Code
from the Project menu. See "Removing Object Code" on page 363 for more information).
This section lists questions and problems with launching the debugger.
The Run
or Debug
command in the CodeWarrior Project
menu is dimmed.
Run
command is only available when creating an application.
Enable Debugger
command from the Project menu to enable the debugger. If you see the Disable Debugger
command instead, the debugger is already enabled.
The Debug
command does nothing.
I get error -27 when I start debugging and -619 when I quit.
You may be using an older version of Ram Doubler that is not compatible with the debugger.
This section covers problems that occur while you are running the debugger.
This section covers problems related to setting and clearing breakpoints.
Some statements don't have dashes in the Breakpoint column, making it impossible to set them.
I set a breakpoint, but it does not work.
This section covers problems related to variables.
I have a variable and I assign it a value, but the value does not change in the debugger.
I notice that values seem to be changing incorrectly. I encounter one of these two problems:
Listing 11.7 is a good example of the kind of code that results in register coloring. Because four different variables are set but never used simultaneously, the compiler has arranged for all four to use the same register. The debugger, however, has no way of knowing that all four variables share the same register, so it shows all four variables changing with each assignment.
void main(void)
{
long a = 0, b = 0, c = 0, d = 0;
a = 1; /* a is set to 1 */
a = 2; /* a is set to 2, b remains unchanged */
a = 3; /* a is set to 3, c remains unchanged */
a = 4; /* a is set to 4, d remains unchanged */
}
For example, in Listing 11.8, with Show Types
selected, variable myMarx
is displayed as having the anonymous type ?anon
x, because its enumerated type has no name. On the other hand, variable myBeatle is shown with type Beatle, because its enumerated type is defined with that name.
// Debugger displays as anonymous type
enum {Groucho,
Harpo,
Chico,
Zeppo } myMarx = Harpo;
// Debugger displays as type Beatle
typedef enum Beatle {John,
Paul,
George,
Ringo} myBeatle = John;
I declared my own data type. Why can I not view a variable as that type?
The symbolics file includes information only about types that are used in the program. Types defined in typedef
statements are not stored in the symbolics file, so you need to view the variable as the type from which it is derived. For example, if you declare a type MyLong
based on the long
data type, you can view it as a long
, but not as a MyLong
. For more information, refer to "Viewing data as different types" on page 458.
Show Types
item from the Data menu to see how the debugger labels the type.
For example, given the Pascal type declaration
TYPE
MYBIGINT = LONGINT;
MYBIGINT(thePtr)
LONGINT(thePtr)
To learn more, see "Expression Limitations" on page 469.
This section covers problems related to source-code files.
When I run my project, I get a warning that says the modification dates do not match.
Attempt to read or write to an invalid address.
The symbolics file contains a data type that the debugger does not support.
Unexpectedly encountered something other than a class name while evaluating an expression.
The command you issued cannot be performed while the program is running.
Watchpoints cannot be set in low memory or in the system heap.
Invalid character constant encountered while evaluating an expression.
Invalid string constant encountered while evaluating an expression.
Invalid token encountered while evaluating an expression.
An ill-formed string was encountered in evaluating an expression.
An invalid character constant was encountered in evaluating an expression.
C/C++ escape sequence in a string was not valid syntax.
Invalid pointer or reference expression encountered while evaluating an expression.
Invalid type encountered while evaluating an expression.
The debugger is unable to display a variable because of bad data in the symbolics file.
For example, you have attempted to assign a 20-byte string to a 10-byte string variable.
The debugger does not recognize a type name you have entered in the View As
dialog box.
String exceeds maximum permissible length.
Unexpectedly encountered something other than a typedef
name while evaluating an expression.
The debugger cannot step execution from this point.
The debugger cannot step out from this point.
Undefined identifier encountered while evaluating an expression.
Unexpected token encountered while evaluating an expression.
An internal error that was not expected to reach the user.
A closing comment bracket is missing.
For example, if r
is a Rect
, *(char*)r
is invalid.
Your symbolics file may have been corrupted.